#include <string.h>
#include "XenItemSniffer.h"

bool XenItemSniffer::itemCompass = true;
static char lastlogtext[255];

XenItemSniffer::XenItemSniffer(IDirect3DDevice9 *pIDirect3DDevice9)
{
	this->pIDirect3DDevice9 = pIDirect3DDevice9;
	Initialize();
}

void XenItemSniffer::Initialize()
{
	xenMemory = new XenMemory();

	D3DVIEWPORT9 viewport;
	pIDirect3DDevice9->GetViewport(&viewport);

	screenWidth = viewport.Width;
	screenHeight = viewport.Height;

	scaleX = screenWidth / DEFAULTSCREENWIDTH;
	scaleY = screenHeight / DEFAULTSCREENHEIGHT;

	D3DXCreateTextureFromFile(pIDirect3DDevice9, ARROW_LOC, &arrowTexture);
	D3DXCreateSprite(pIDirect3DDevice9, &arrowSprite);

	ZeroMemory(&fitemList, sizeof(D3DXFONT_DESC));
	strcpy(fitemList.FaceName, "Arial");
	fitemList.Height = -16;
	D3DXCreateFontIndirect(pIDirect3DDevice9, &fitemList, &itemListFont);

	itemCompass = true;
}

void XenItemSniffer::Render()
{
	if(PacketHandler::itemSniffer && xenMemory->ReadPage() == 0) {
		int xLoc = xenMemory->ReadLocX();
		int yLoc = xenMemory->ReadLocY();

		if (!PacketHandler::itemsLock) {
			PacketHandler::itemsLock = true;

			itemList.clear();
			itemLocations.clear();
			
			for (int i = 0; i < PacketHandler::items.size(); ++i) {
				itemLocations.push_back(D3DXVECTOR2(PacketHandler::items[i].x, PacketHandler::items[i].y));

				string xDir = xLoc == PacketHandler::items[i].x ? "" : xLoc < PacketHandler::items[i].x ? "+" : "-";
				string yDir = yLoc == PacketHandler::items[i].y ? "" : yLoc < PacketHandler::items[i].y ? "+" : "-";
				itemList += PacketHandler::items[i].name + " X: " + Utils::ToString<int>(PacketHandler::items[i].x) + xDir + " Y: " + Utils::ToString<int>(PacketHandler::items[i].y) + yDir + "\n";
			}
			PacketHandler::itemsLock = false;
		}


		RECT itemSnifferTextRect = { 10, 75, 0, 0 };
		itemListFont->DrawText(NULL, itemList.c_str(), -1, &itemSnifferTextRect, DT_CALCRECT, 0);
		int itemSnifferTextWidth = (itemSnifferTextRect.right - itemSnifferTextRect.left);
		itemSnifferTextRect.left = screenWidth - itemSnifferTextWidth - 10;
		itemSnifferTextRect.right = itemSnifferTextRect.left + itemSnifferTextWidth;
		itemListFont->DrawText(NULL, itemList.c_str(), -1, &itemSnifferTextRect, DT_RIGHT, D3DCOLOR_XRGB(255, 255, 255));

		RECT itemSnifferEnabledTextRect = { screenWidth - 200, screenHeight - 30, 0, 0 };
		itemListFont->DrawText(NULL, ITEMSNIFFERSTR, -1, &itemSnifferEnabledTextRect, DT_CALCRECT, 0);
		itemListFont->DrawText(NULL, ITEMSNIFFERSTR, -1, &itemSnifferEnabledTextRect, DT_RIGHT, D3DCOLOR_XRGB(255, 255, 255));

		
		for (int i = 0; i < itemLocations.size(); ++i) {
			RECT textOverItemRect = {0, 0, 0, 0};
			int screenCenterX = screenWidth/2;
			int screenCenterY = screenHeight/2;
			string itemName = PacketHandler::items[i].name;
			int distanceX = itemLocations[i].x - xLoc;
			int distanceY = itemLocations[i].y - yLoc;
			int itemLocX = (itemLocations[i].x-1)*20+10;
			int itemLocY = (itemLocations[i].y-1)*20+10;
			
/*			char logtext[255];
			static char logtextold[255];
			sprintf_s(logtext, 255, "Item: %d,%d  Player: %d, %d\n", itemLocX, itemLocY, xLocLong, yLocLong);
			if (strcmp(logtext, logtextold)) {
				Utils::Log("xenergy\\testes.log", logtext);
				strcpy_s(logtextold, logtext);
			}
*/			
			textOverItemRect.left = screenCenterX + (distanceX*60) - 20;
			textOverItemRect.top = screenCenterY + (distanceY*60) - 20;
			itemListFont->DrawTextA(NULL, itemName.c_str(), -1, &textOverItemRect, DT_CALCRECT, 0);
			itemListFont->DrawTextA(NULL, itemName.c_str(), -1, &textOverItemRect, DT_RIGHT, D3DCOLOR_XRGB(255, 255, 0));
		}
		
		//Draw Arrows
		if(itemCompass) {
			D3DSURFACE_DESC arrowDesc;
			arrowTexture->GetLevelDesc(0, &arrowDesc);

			D3DXVECTOR2 arrowScale;
			arrowScale.x = scaleX;
			arrowScale.y = scaleY;

			arrowSprite->Begin(D3DXSPRITE_ALPHABLEND);
			
		
			for (int i = 0; i < itemLocations.size(); ++i) {
				//Position the arrow based on the location of the items
				if(itemLocations[i].x != xLoc || itemLocations[i].y != yLoc) {
					int x = itemLocations[i].x - xLoc;
					int y = itemLocations[i].y - yLoc;
					float angle = atan2((float)y, (float)x);

					D3DXVECTOR2 arrowPos;
					arrowPos.x = (screenWidth / 2) - (arrowDesc.Width * scaleX / 2)  + (cos(angle) * 50 * scaleX);
					arrowPos.y = (screenHeight / 2) - (arrowDesc.Height * scaleY / 2) + (sin(angle) * 50 * scaleY);

					D3DXMATRIX arrowMatrix;
					D3DXMatrixTransformation2D(&arrowMatrix, NULL, 0.0, &arrowScale, &D3DXVECTOR2(arrowDesc.Width * scaleX / 2, arrowDesc.Height * scaleY / 2), angle, &arrowPos);
					arrowSprite->SetTransform(&arrowMatrix);
					arrowSprite->Draw(arrowTexture, NULL, NULL, NULL, 0xFFFFFFFF);
				}
			}
			arrowSprite->End();
		}
	}
}

void XenItemSniffer::StartSnifferThread()
{
	HANDLE processPacketsThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)this->ProcessPackets, NULL, 0, NULL);
	SetThreadPriority(processPacketsThread, THREAD_PRIORITY_LOWEST);
}

DWORD WINAPI XenItemSniffer::ProcessPackets(LPVOID lpParameter)
{

	static bool key1Released = true;
	static bool key2Released = true;
	while (true) {
		if (Input::KeysDown(ConfigFile::ItemSnifferInput)) {
			if (key1Released) {
				if (PacketHandler::itemSniffer) {
					PacketHandler::itemSniffer = false;
					//PacketHandler::Detach();
					//Utils::Log(LOGFILE, "Item Sniffer Disabled\n");

				} else { 
					PacketHandler::itemSniffer = true;
					//Utils::Log(LOGFILE, "Item Sniffer Enabled\n");
				}
			}
			key1Released = false;
		} else {
			key1Released = true;
		}

		if (Input::KeysDown(ConfigFile::ItemCompass)) {
			if (key2Released) {
				if (itemCompass) {
					itemCompass = false;
					//PacketHandler::Detach();
					Utils::Log(LOGFILE, "Item Compass Disabled\n");

				} else { 
					itemCompass = true;
					Utils::Log(LOGFILE, "Item Compass Enabled\n");
				}
			}
			key2Released = false;
		} else {
			key2Released = true;
		}

		PacketHandler::ProcessPacket();
		Sleep(30);
	}
}

void XenItemSniffer::Release()
{
	itemListFont->Release();
	arrowTexture->Release();
	arrowSprite->Release();

	delete(xenMemory);
}

int XenItemSniffer::ReadMemLocUInt(int address)
{
	HANDLE Process = GetCurrentProcess();
	unsigned int memLocInt;
	ReadProcessMemory(Process, (LPCVOID)address, &memLocInt, sizeof(int), NULL);

	return memLocInt;
}